from flask import Blueprint, request, jsonify
from werkzeug.exceptions import BadRequest
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
import datetime
from functools import wraps
from app import db
from config import Config
from app.auth.models import User
from app.auth.schemas import user_schema, users_schema, user_auth_schema

# 创建认证模块的蓝图，用于组织路由
auth_bp = Blueprint('auth', __name__)


# JWT认证装饰器
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None

        # 从请求头中获取token
        if 'Authorization' in request.headers:
            auth_header = request.headers['Authorization']
            try:
                token = auth_header.split(" ")[1]  # 假设格式为 'Bearer token'
            except IndexError:
                return jsonify({'message': 'Token is missing!'}), 401

        if not token:
            return jsonify({'message': 'Token is missing!'}), 401

        try:
            # 解码token
            data = jwt.decode(token, Config.SECRET_KEY, algorithms=["HS256"])
            current_user = User.query.get(data['user_id'])
        except:
            return jsonify({'message': 'Token is invalid!'}), 401

        return f(current_user, *args, **kwargs)

    return decorated


@auth_bp.route('/', methods=['GET'])
def auth_root():
    # 认证模块根路由
    return jsonify({'message': 'This is the authentication API endpoint'}), 200


@auth_bp.route('/register', methods=['POST'])
def register():
    """
    用户注册接口
    ---
    请求参数：
      - username: 用户名（必填，唯一）
      - email: 邮箱（必填，唯一）
      - password: 密码（必填）
      - phone: 电话（可选）
      - address: 地址（可选）
    返回：
      - 成功：创建的用户信息
      - 失败：错误信息
    """
    data = request.get_json()
    
    if not data:
        raise BadRequest('No input data provided')
    
    # 验证必填字段
    username = data.get('username')
    email = data.get('email')
    password = data.get('password')
    
    if not username or not email or not password:
        raise BadRequest('Missing required fields: username, email, password')
    
    # 检查用户名是否已存在
    if User.query.filter_by(username=username).first():
        return jsonify({'success': False, 'message': 'Username already exists'}), 400
    
    # 检查邮箱是否已存在
    if User.query.filter_by(email=email).first():
        return jsonify({'success': False, 'message': 'Email already exists'}), 400
    
    # 创建新用户，密码进行哈希处理
    hashed_password = generate_password_hash(password, method='pbkdf2:sha256')
    
    user = User(
        username=username,
        email=email,
        password=hashed_password,
        phone=data.get('phone'),
        address=data.get('address')
    )
    
    db.session.add(user)
    db.session.commit()
    
    return jsonify({
        'success': True,
        'message': 'Registration successful!',
        'data': user_schema.dump(user)
    }), 201


@auth_bp.route('/login', methods=['POST'])
def login():
    """
    用户登录接口
    ---
    请求参数：
      - username: 用户名（必填）
      - password: 密码（必填）
    返回：
      - 成功：JWT token和用户信息
      - 失败：错误信息
    """
    data = request.get_json()
    
    if not data:
        raise BadRequest('No input data provided')
    
    username = data.get('username')
    password = data.get('password')
    
    if not username or not password:
        raise BadRequest('Missing required fields: username, password')
    
    # 查询用户信息
    user = User.query.filter_by(username=username).first()
    
    # 验证用户和密码
    if not user:
        return jsonify({'success': False, 'message': '用户名不存在'}), 401
    elif not check_password_hash(user.password, password):
        return jsonify({'success': False, 'message': '密码错误'}), 401
    
    # 生成JWT token，有效期为30分钟
    token = jwt.encode({
        'user_id': user.id,
        'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
    }, Config.SECRET_KEY, algorithm="HS256")
    
    return jsonify({
        'success': True,
        'message': 'Login successful!',
        'token': token,
        'user': user_schema.dump(user)
    }), 200


@auth_bp.route('/profile', methods=['GET'])
@token_required
def get_profile(current_user):
    """
    获取当前用户个人信息接口（需要认证）
    ---
    返回：
      - 当前登录用户的详细信息
    """
    return jsonify({
        'success': True,
        'data': user_schema.dump(current_user)
    }), 200


@auth_bp.route('/profile', methods=['PUT'])
@token_required
def update_profile(current_user):
    """
    更新当前用户个人信息接口（需要认证）
    ---
    请求参数：
      - username: 用户名（可选，唯一）
      - email: 邮箱（可选，唯一）
      - phone: 电话（可选）
      - address: 地址（可选）
      - avatar: 头像URL（可选）
    返回：
      - 成功：更新后的用户信息
      - 失败：错误信息
    """
    data = request.get_json()
    
    if not data:
        raise BadRequest('No input data provided')
    
    # 更新用户信息
    if 'username' in data and data['username'] != current_user.username:
        if User.query.filter_by(username=data['username']).first():
            return jsonify({'success': False, 'message': 'Username already exists'}), 400
        current_user.username = data['username']
    
    if 'email' in data and data['email'] != current_user.email:
        if User.query.filter_by(email=data['email']).first():
            return jsonify({'success': False, 'message': 'Email already exists'}), 400
        current_user.email = data['email']
    
    if 'phone' in data:
        current_user.phone = data['phone']
    
    if 'address' in data:
        current_user.address = data['address']
    
    if 'avatar' in data:
        current_user.avatar = data['avatar']
    
    db.session.commit()
    
    return jsonify({
        'success': True,
        'message': 'Profile updated successfully!',
        'data': user_schema.dump(current_user)
    }), 200


@auth_bp.route('/change-password', methods=['PUT'])
@token_required
def change_password(current_user):
    """
    修改密码接口（需要认证）
    ---
    请求参数：
      - current_password: 当前密码（必填）
      - new_password: 新密码（必填）
    返回：
      - 成功：成功信息
      - 失败：错误信息
    """
    data = request.get_json()
    
    if not data:
        raise BadRequest('No input data provided')
    
    current_password = data.get('current_password')
    new_password = data.get('new_password')
    
    if not current_password or not new_password:
        raise BadRequest('Missing required fields: current_password, new_password')
    
    # 验证当前密码
    if not check_password_hash(current_user.password, current_password):
        return jsonify({'success': False, 'message': 'Current password is incorrect'}), 401
    
    # 更新密码
    current_user.password = generate_password_hash(new_password, method='pbkdf2:sha256')
    db.session.commit()
    
    return jsonify({
        'success': True,
        'message': 'Password changed successfully!'
    }), 200


@auth_bp.route('/admin/users', methods=['GET'])
@token_required
def get_all_users(current_user):
    """
    获取所有用户列表接口（仅管理员可访问）
    ---
    返回：
      - 系统中所有用户的基本信息列表
    """
    # 检查是否为管理员
    if not current_user.is_admin:
        return jsonify({'success': False, 'message': 'Admin access required'}), 403
    
    users = User.query.all()
    
    return jsonify({
        'success': True,
        'count': len(users),
        'data': users_schema.dump(users)
    }), 200


# --------------------------
# 测试专用：返回所有用户信息（无需管理员权限）
# --------------------------
@auth_bp.route('/test/get-all-users', methods=['GET'])
@token_required  # 仅需登录（普通用户也能访问），无需管理员权限
def test_get_all_users(current_user):
    """
    测试接口：返回所有用户信息（仅用于测试，正式环境需删除）
    ---
    仅需普通用户登录（无需管理员权限），直接返回所有用户列表
    """
    # 查询所有用户
    all_users = User.query.all()

    # 返回序列化后的所有用户数据
    return jsonify({
        'success': True,
        'test_note': '此接口仅用于测试，正式环境请删除或限制权限',
        'total_users': len(all_users),  # 用户总数
        'users': users_schema.dump(all_users)  # 所有用户详细信息
    }), 200


# --------------------------
# 测试专用：完全绕过JWT认证，直接返回所有用户
# 注意：正式环境必须删除！仅本地测试用！
# --------------------------
@auth_bp.route('/test/all-users-no-auth', methods=['GET'])
def test_all_users_no_auth():
    """
    测试接口：无需登录，直接返回所有用户信息
    用途：快速验证用户数据是否正常，绕过JWT认证
    """
    try:
        # 直接查询数据库中所有用户
        all_users = User.query.all()

        # 返回用户数据（包含总数和列表）
        return jsonify({
            'success': True,
            'test_warning': '此接口无认证！正式环境必须删除！',
            'total_users': len(all_users),  # 统计用户总数
            'all_users': users_schema.dump(all_users)  # 所有用户详细信息
        }), 200  # 200表示请求成功

    except Exception as e:
        # 捕获异常，返回错误信息（方便排查bug）
        return jsonify({
            'success': False,
            'error': '获取用户失败',
            'error_detail': str(e)  # 显示具体错误原因（如数据库连接问题）
        }), 500  # 500表示服务器内部错误


# --------------------------
# 测试专用：根据用户名获取密码哈希值
# 注意：仅用于开发测试！正式环境必须删除！
# --------------------------
@auth_bp.route('/test/get-user-password-hash/<username>', methods=['GET'])
def test_get_user_password_hash(username):
    """
    测试接口：根据用户名获取密码哈希值
    用途：开发测试时查看密码加密后的哈希值，方便调试
    注意：此接口非常不安全！正式环境必须删除！
    """
    try:
        # 根据用户名查询用户
        user = User.query.filter_by(username=username).first()
        
        if not user:
            return jsonify({
                'success': False,
                'test_warning': '此接口仅供测试！正式环境必须删除！',
                'error': '用户不存在',
                'username': username
            }), 404
        
        # 返回用户信息（包含密码哈希值和测试用明文密码提示）
        return jsonify({
            'success': True,
            'test_warning': '此接口非常不安全！正式环境必须删除！',
            'username': user.username,
            'password_hash': user.password,  # 返回密码哈希值
            'plain_password_hint': '数据库中不存储明文密码！请使用 /test/set-user-password 接口设置新密码以查看明文',
            'last_set_plain_password': password if 'password' in locals() else None  # 如果存在明文密码则返回
        }), 200
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': '获取用户信息失败',
            'error_detail': str(e)
        }), 500


# --------------------------
# 测试专用：设置用户明文密码（用于测试）
# 注意：正式环境必须删除！仅本地测试用！
# --------------------------
@auth_bp.route('/test/set-user-password', methods=['POST'])
def test_set_user_password():
    """
    测试接口：设置或更新用户的明文密码
    用途：开发测试时快速设置用户密码，避免无法登录的问题
    注意：此接口仅用于测试环境！正式环境必须删除！
    """
    try:
        # 获取请求参数
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')
        
        # 参数验证
        if not username or not password:
            return jsonify({
                'success': False,
                'test_warning': '此接口仅供测试！正式环境必须删除！',
                'error': '用户名和密码不能为空'
            }), 400
        
        # 查找用户，如果不存在则创建新用户
        user = User.query.filter_by(username=username).first()
        
        if not user:
            # 创建新用户
            user = User(username=username)
            db.session.add(user)
        
        # 设置密码（自动哈希处理）
        user.password = generate_password_hash(password)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'test_warning': '此接口仅用于测试环境！正式环境必须删除！',
            'message': f'用户 {username} 的密码已成功设置为：{password}',
            'username': username,
            'plain_password': password  # 返回明文密码供测试使用
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'error': '设置密码失败',
            'error_detail': str(e)
        }), 500


@auth_bp.route('/delete-account', methods=['DELETE'])
@token_required
def delete_account(current_user):
    """
    用户注销账号接口（需要认证）
    --- 
    返回：
      - 成功：成功信息
      - 失败：错误信息
    """
    try:
        # 导入其他相关模型
        from app.likes.models import Like
        from app.favorites.models import Favorite
        from app.comments.models import Comment
        from app.recipes.models import Recipe
        
        # 先删除用户的所有菜谱（以及相关的步骤、食材、评论等）
        recipes = Recipe.query.filter_by(user_id=current_user.id).all()
        for recipe in recipes:
            # 这些会通过关系的cascade选项自动删除
            db.session.delete(recipe)
        
        # 删除用户的所有点赞
        likes = Like.query.filter_by(user_id=current_user.id).all()
        for like in likes:
            db.session.delete(like)
        
        # 删除用户的所有收藏
        favorites = Favorite.query.filter_by(user_id=current_user.id).all()
        for favorite in favorites:
            db.session.delete(favorite)
        
        # 删除用户的所有评论
        comments = Comment.query.filter_by(user_id=current_user.id).all()
        for comment in comments:
            db.session.delete(comment)
        
        # 删除用户
        db.session.delete(current_user)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '账号已成功注销，所有用户信息已删除'
        }), 200
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': '账号注销失败',
            'error_detail': str(e)
        }), 500
